--[[
ChatLink.lua
by Yrys - Hellscream <http://twpa.net/contact.php>

ChatLink enables linking items, enchants, spells, talents, quests, and achievements in private chat channels. ChatLink by default will not work in public channels such as General or Trade to avoid undue spam. Also, note that other people will need this addon to see your links in chat channels correctly.


Version history:
- 1.4.1.30000 (2008-11-25): Swapped back to the newer item link format.  Also fixed a possible bug with profession links.  Thanks to Sylvanaar for pointing it out.
- 1.4.0.30000 (2008-09-16): Updated for 3.0.2 patch.  Fixed item and talent links; added profession and achievement links.
- 1.3.0.20400 (2008-04-07): Updated for 2.4.0 patch.  Added spell, talent and quest linking support.
- 1.2.0.20300 (2008-03-08): Updated for 2.3.0 patch.
- 1.2.0.20200 (2007-09-27): Updated for 2.2.0 patch.
- 1.2.0.20100 (2007-04-28): Verified recipe link support.  Added a warning message when other chatlink-type addons are detected, and another warning if a newer ChatLink link style is detected.
- 1.1.4.20003 (2007-01-17): More Burning Crusade fixes (itemIDs can now also be negative).
- 1.1.3.20003 (2007-01-14): Updated for 2.0.3 patch.
- 1.1.3.20000 (2006-11-11): Compatibility fixes for Burning Crusade and UI 2.0.
- 1.1.3.11200 (2006-11-05): Added the guild recruitment channel to the excluded channels.
- 1.1.2.11200 (2006-09-29): Re-added compatibility with links before 1.1.0, and added future compatibility as well.
- 1.1.0.11200 (2006-09-27): Updated for 1.12 patch, and added enchant link support.
- 1.0.4.11100 (2006-07-24): Updated for 1.11 patch.
- 1.0.4.11000 (2006-03-17): Updated for 1.10 patch.
- 1.0.4.10900 (2005-12-02): Updated for 1.9 patch.
- 1.0.4.1800  (2005-09-30): Updated for 1.8 patch; now with French localization!  Thanks Viny!
- 1.0.3.1700  (2005-09-07): Updated for 1.7 patch; added German localization. Thanks Getch!
- 1.0.2.1600  (2005-07-12): Updated for 1.6 patch.
- 1.0.2.1500  (2005-06-07): Updated for 1.5 patch.
- 1.0.2.1300  (2005-04-14): Fixed a bug with nil strings in AddMessage.
- 1.0.1.1300  (2005-04-06): Added support for links in other chat windows.
- 1.0.0.1300  (2005-04-05): Initial release.


To addon developers:
Feel free to use this code.  I would appreciate it if you let me know and/or give credit.  (It's a bummer to have someone take your work and claim it as their own.)  If you're looking to make an addon compatible with ChatLink links, here's the current formatting.

Items: {CLINK:item:<color in hex>:<item ID and item data - 9 fields>:<item name>}
Enchant recipes: {CLINK:enchant:<color in hex>:<enchant ID>:<enchant name>}
Spells: {CLINK:spell:<color in hex>:<spell ID>:<spell name>}
Quests: {CLINK:quest:<color in hex>:<quest ID>:<quest level>:<quest name>}
Professions: {CLINK:trade:<profession ID>:<current skill>:<max skill>:<player id?>:<recipe hash>:<profession name>}
Talents: {CLINK:talent:<talent ID>:<points in talent - 2>:<talent name>}
Achievements: {CLINK:achievement:<achievement ID>:<player id?>:<have it?>:<month>:<day>:<year>:<4 additional fields>:<achievement name>}
Legacy item links (pre ChatLink 1.1.0): {CLINK:<color in hex>:<item ID and item data - 9 fields>:<item name>}

Notes:
- Items: Items had an extra field added in WotLK and are up to 9 data fields.
- Legacy item links: Versions of ChatLink before 1.4.1 (and possibly other chat link addons) sent item links using the legacy format.  You may want to capture and decode both item link formats for compatibility.
- Quests: You pretty much have to discard the color you get when decoding quest CLINKs.  Since the person sending the quest may not be the same level as you, the quest won't have the same color for you as for them.  See ChatLink_SetQuestLinkColor below.

Send me an e-mail if you have any questions!
-Yrys

]]


-- ENGLISH LANGUAGE STRINGS.
-- Function strings.
local STR_CHATLINK_LOADED = "ChatLink %s loaded."
local STR_CHATLINK_LOADED_WARNING = "ChatLink %s loaded, but other chat addons were detected.  Conflicts may occur."

-- System channel names.
local STR_GENERAL = "General -"
local STR_TRADE = "Trade -"
local STR_LFG = "LookingForGroup -"
local STR_LOCALDEF = "LocalDefense -"
local STR_WORLDDEF = "WorldDefense"
local STR_GUILDREC = "GuildRecruitment - "



if (GetLocale() == "zhCN") then
	STR_GENERAL = "综合 -"
	STR_TRADE = "交易 -"
	STR_LFG = "寻求组队"
	STR_LOCALDEF = "本地防务 -"
	STR_WORLDDEF = "世界防务"
	STR_GUILDREC = "公会招募 -"
elseif (GetLocale() == "zhTW") then
	STR_GENERAL = "綜合 -"
	STR_TRADE = "交易 -"
	STR_LFG = "尋求組隊"
	STR_LOCALDEF = "本地防務 -"
	STR_WORLDDEF = "世界防務"
	STR_GUILDREC = "公會招募 -"
end


-- Variables.
CHATLINK_VER = "1.4.1.30000"
local AddMessage1_Original = nil
local AddMessage2_Original = nil
local AddMessage3_Original = nil
local AddMessage4_Original = nil
local AddMessage5_Original = nil
local AddMessage6_Original = nil
local AddMessage7_Original = nil
local SendChatMessage_Original = nil



function ChatLink_OnLoad()

		AddMessage1_Original = DEFAULT_CHAT_FRAME.AddMessage
		DEFAULT_CHAT_FRAME.AddMessage = ChatLink_AddMessage1

		AddMessage2_Original = ChatFrame2.AddMessage
		ChatFrame2.AddMessage = ChatLink_AddMessage2

		AddMessage3_Original = ChatFrame3.AddMessage
		ChatFrame3.AddMessage = ChatLink_AddMessage3

		AddMessage4_Original = ChatFrame4.AddMessage
		ChatFrame4.AddMessage = ChatLink_AddMessage4

		AddMessage5_Original = ChatFrame5.AddMessage
		ChatFrame5.AddMessage = ChatLink_AddMessage5

		AddMessage6_Original = ChatFrame6.AddMessage
		ChatFrame6.AddMessage = ChatLink_AddMessage6

		AddMessage7_Original = ChatFrame7.AddMessage
		ChatFrame7.AddMessage = ChatLink_AddMessage7

		SendChatMessage_Original = SendChatMessage
		SendChatMessage = ChatLink_SendChatMessage

	-- Hook functions.
	--[[if DEFAULT_CHAT_FRAME.AddMessage ~= ChatLink_AddMessage1 then
		AddMessage1_Original = DEFAULT_CHAT_FRAME.AddMessage
		DEFAULT_CHAT_FRAME.AddMessage = ChatLink_AddMessage1
	end
	if ChatFrame2 and ChatFrame2.AddMessage ~= ChatLink_AddMessage2 then
		AddMessage2_Original = ChatFrame2.AddMessage
		ChatFrame2.AddMessage = ChatLink_AddMessage2
	end
	if ChatFrame3 and ChatFrame3.AddMessage ~= ChatLink_AddMessage3 then
		AddMessage3_Original = ChatFrame3.AddMessage
		ChatFrame3.AddMessage = ChatLink_AddMessage3
	end
	if ChatFrame4 and ChatFrame4.AddMessage ~= ChatLink_AddMessage4 then
		AddMessage4_Original = ChatFrame4.AddMessage
		ChatFrame4.AddMessage = ChatLink_AddMessage4
	end
	if ChatFrame5 and ChatFrame5.AddMessage ~= ChatLink_AddMessage5 then
		AddMessage5_Original = ChatFrame5.AddMessage
		ChatFrame5.AddMessage = ChatLink_AddMessage5
	end
	if ChatFrame6 and ChatFrame6.AddMessage ~= ChatLink_AddMessage6 then
		AddMessage6_Original = ChatFrame6.AddMessage
		ChatFrame6.AddMessage = ChatLink_AddMessage6
	end
	if ChatFrame7 and ChatFrame7.AddMessage ~= ChatLink_AddMessage7 then
		AddMessage7_Original = ChatFrame7.AddMessage
		ChatFrame7.AddMessage = ChatLink_AddMessage7
	end
	if SendChatMessage ~= ChatLink_SendChatMessage then
		SendChatMessage_Original = SendChatMessage
		SendChatMessage = ChatLink_SendChatMessage
	end]]
	
	-- Check for other chat addons, and show conflict warning.
	-- Also, show loaded message.
	--[[if IsAddOnLoaded ("ChatBox") or IsAddOnLoaded ("Chatmanager")
		or IsAddOnLoaded ("ChatMod") or IsAddOnLoaded ("Prat")
		or IsAddOnLoaded ("GuildAds") or IsAddOnLoaded ("Chatter")
	then
		DEFAULT_CHAT_FRAME:AddMessage (string.format (STR_CHATLINK_LOADED_WARNING, CHATLINK_VER))
	else
		DEFAULT_CHAT_FRAME:AddMessage (string.format (STR_CHATLINK_LOADED, CHATLINK_VER))
	end]]
	--f:UnregisterEvent("VARIABLES_LOADED")
end

-- Get color for quest level -- based off Blizzard's code in FrameXML/QuestLogFrame.lua
function ChatLink_GetDifficultyColor(level)
	local levelDiff = level - UnitLevel("player");
	local color
	if ( levelDiff >= 5 ) then							-- red / impossible
		color = "ff2020";
	elseif ( levelDiff >= 3 ) then						-- orange / very difficult
		color = "ff8040";
	elseif ( levelDiff >= -2 ) then						-- yellow / difficult
		color = "ffff00";
	elseif ( -levelDiff <= GetQuestGreenRange() ) then	-- green / standard
		color = "40c040";
	else												-- grey / trivial
		color = "808080";
	end
	return color;
end



-- Update the color of a quest link based on player level.
function ChatLink_SetQuestLinkColor(questId, questLevel, questName)
	if questId and questLevel and questName
	then
		local newQuestColor = ChatLink_GetDifficultyColor (questLevel)
		return "|cff" .. newQuestColor .. "|Hquest:" .. questId .. ":" .. questLevel .. "|h[" .. questName .. "]|h|r"
	else
		return nil
	end
end



-- Turn CLINKs into normal item and enchant links.
function ChatLink_Decompose (chatstring)
	if chatstring then
		chatstring = string.gsub (chatstring, "{CLINK:item:(%x+):(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:enchant:(%x+):(%-?%d-):([^}]-)}", "|c%1|Henchant:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:quest:%x+:(%-?%d-):(%-?%d-):([^}]-)}", ChatLink_SetQuestLinkColor)
		chatstring = string.gsub (chatstring, "{CLINK:spell:(%x+):(%-?%d-):([^}]-)}", "|c%1|Hspell:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:talent:(%x+):(%-?%d-:%-?%d-):([^}]-)}", "|c%1|Htalent:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:achievement:(%x+):(%-?%d-:%x-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-):([^}]-)}", "|c%1|Hachievement:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:trade:(%x+):(%-?%d-:%-?%d-:%-?%d-:%x-:[^}:]+):([^}]-)}","|c%1|Htrade:%2|h[%3]|h|r")

		-- For backward compatibility with older item links.
		chatstring = string.gsub (chatstring, "{CLINK:(%x+):(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")

		-- Forward compatibility, for future clink structure changes.
		chatstring = string.gsub (chatstring, "{CLINK(%d):%[?([^:}%]]-)%]?:([^:}]-)[^}]-}", "%2")
	end
	return chatstring
end



-- Turn item and enchant links into CLINKs.
function ChatLink_Compose (chatstring)
	if chatstring then
--		1.10 item links: reactivated again.
		chatstring = string.gsub (chatstring, "|c(%x+)|H(item):(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
--		Old item links: disabled, may remove soon.
--		chatstring = string.gsub (chatstring, "|c(%x+)|Hitem:(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%1:%2:%3}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(enchant):(%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(quest):(%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(spell):(%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(talent):(%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(achievement):(%-?%d-:%x-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(trade):(%-?%d-:%-?%d-:%-?%d-:%x-:[^|:]+)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
	end
	return chatstring
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage1(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage1_Original (t, "|c5050ffffUnprocessed: |r" .. s, select (1, ...))

	s = ChatLink_Decompose (s)

	-- Debug: Show raw links.
--	AddMessage1_Original (t, "|c5050ffffRaw links: |r" .. string.gsub(s, "|", "||"), select (1, ...))

	-- Pass along to original function.
	AddMessage1_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage2(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage2_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage3(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage3_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage4(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage4_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage5(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage5_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage6(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage6_Original (t, s, select (1, ...))
end



-- Translate CLINKs back into normal text on incoming messages.
function ChatLink_AddMessage7(t, s, ...)
	-- Debug: Show untranslated message.
--	AddMessage_Original (t, "|c5050ffffBefore: |r" .. s, select (1, ...))
	s = ChatLink_Decompose (s)

	-- Pass along to original function.
	AddMessage7_Original (t, s, select (1, ...))
end



-- Translate item links into CLINKs on outgoing non-system channel messages.
function ChatLink_SendChatMessage (msg, ...)
	local chan_num, chan_name = nil
	system, language, channel = select (1, ...)

	if system == "CHANNEL" then
		chan_num, chan_name = GetChannelName (channel)
		if chan_name and
		--[[not string.find (chan_name, STR_GENERAL) and
		not string.find (chan_name, STR_TRADE) and
		not string.find (chan_name, STR_LFG) and
		not string.find (chan_name, STR_LOCALDEF) and
		not string.find (chan_name, STR_WORLDDEF) and
		not string.find (chan_name, STR_GUILDREC) then]]
		( not string.find(chan_name, GENERAL) ) and
		( not string.find(chan_name, TRADE) ) and
		( not string.find(chan_name, CHAT_MSG_GUILD) ) and
		( not string.find(chan_name, CHAT_MSG_RAID) ) and
		( not string.find(chan_name, CHAT_MSG_PARTY) ) and
		( not string.find(chan_name, CHAT_MSG_RAID_LEADER) ) and
		( not string.find(chan_name, CHAT_MSG_RAID_WARNING) ) then
			msg = ChatLink_Compose (msg)
		end
	end

	-- Pass along to original function.
	SendChatMessage_Original (msg, select (1, ...))
end
